/**
 * 
 */
package info.niwota.web.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpCookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import jvs.peer.util.Log;
import x.org.apache.http.Header;
import x.org.apache.http.HeaderElement;
import x.org.apache.http.HttpRequest;
import x.org.apache.http.impl.DefaultHttpServerConnection;
import x.org.apache.http.protocol.BasicHttpContext;
import x.org.apache.http.protocol.ExecutionContext;
import x.org.apache.http.protocol.HttpContext;

/**
 * @author qiangli
 * 
 */
public class HttpServletRequestWrapper implements HttpServletRequest {
	public static final String PARAMETERS_KEY = "http.parameters";

	private static final String TAG = "HttpServletRequestWrapper";

	private final HttpRequest req;
	private final BasicHttpContext context;
	private final DefaultHttpServerConnection conn;

	private final Map<String, String> params;

	public HttpServletRequestWrapper(HttpRequest req, HttpContext context) {
		this.req = req;
		this.context = (BasicHttpContext) context;
		this.conn = (DefaultHttpServerConnection) context
				.getAttribute(ExecutionContext.HTTP_CONNECTION);
		this.params = (Map<String, String>) context
				.getAttribute(HttpServletRequestWrapper.PARAMETERS_KEY);
	}

	
	public Object getAttribute(String name) {
		return context.getAttribute(name);
	}

	
	public Enumeration getAttributeNames() {
		return Collections.enumeration(context.map.keySet());
	}

	
	public String getCharacterEncoding() {
		return null;
	}

	
	public void setCharacterEncoding(String env)
			throws UnsupportedEncodingException {
	}

	
	public int getContentLength() {
		return -1;
	}

	
	public String getContentType() {
		return null;
	}

	
	public ServletInputStream getInputStream() throws IOException {
		return null;
	}

	
	public String getParameter(String name) {
		return params.get(name);
	}

	
	public Enumeration<String> getParameterNames() {
		return Collections.enumeration(params.keySet());
	}

	
	public String[] getParameterValues(String name) {
		return params.values().toArray(new String[0]);
	}

	
	public Map<String, String> getParameterMap() {
		return params;
	}

	
	public String getProtocol() {
		return req.getRequestLine().getProtocolVersion().toString();
	}

	
	public String getScheme() {
		// TODO
		return "http";
	}

	
	public String getServerName() {
		return conn.getLocalAddress().getHostName();
	}

	
	public int getServerPort() {
		return conn.getLocalPort();
	}

	
	public BufferedReader getReader() throws IOException {
		return null;
	}

	
	public String getRemoteAddr() {
		return conn.getRemoteAddress().getHostAddress();
	}

	
	public String getRemoteHost() {
		return conn.getRemoteAddress().getHostName();
	}

	
	public void setAttribute(String name, Object o) {
		context.setAttribute(name, o);
	}

	
	public void removeAttribute(String name) {
		context.removeAttribute(name);
	}

	
	public Locale getLocale() {
		Header h = req.getLastHeader("Accept-Language");
		HeaderElement[] he = h.getElements();
		if (he.length == 0) {
			return Locale.getDefault();
		}
		String[] la = he[0].getName().split("-");
		return la.length == 1 ? new Locale(la[0]) : new Locale(la[0], la[1]);
	}

	
	public Enumeration<Locale> getLocales() {
		ArrayList<Locale> al = new ArrayList<Locale>();
		Header h = req.getLastHeader("Accept-Language");
		HeaderElement[] he = h.getElements();
		if (he.length == 0) {
			al.add(Locale.getDefault());
		} else {
			for (int i = 0; i < he.length; i++) {
				String[] la = he[i].getName().split("-");
				al.add(la.length == 1 ? new Locale(la[0]) : new Locale(la[0], la[1]));
			}
		}
		return Collections.enumeration(al);
	}

	
	public boolean isSecure() {
		return getScheme().equalsIgnoreCase("https");
	}

	
	public String getRealPath(String path) {
		return null;
	}

	
	public int getRemotePort() {
		return conn.getRemotePort();
	}

	
	public String getLocalName() {
		return conn.getLocalAddress().getHostName();
	}

	
	public String getLocalAddr() {
		return conn.getLocalAddress().getHostAddress();
	}

	
	public int getLocalPort() {
		return conn.getLocalPort();
	}

	
	public String getAuthType() {
		return null;
	}

	
	public Cookie[] getCookies() {
		ArrayList<HttpCookie> cookies = new ArrayList<HttpCookie>();
		Header[] ha = req.getHeaders("Cookie");
		if (ha != null && ha.length > 0) {
			for (int i = 0;i < ha.length; i++) {
				cookies.addAll(HttpCookie.parse(ha[i].getValue()));
			}
		}
		
		Header[] ha2 = req.getHeaders("Cookie2");
		if (ha2 != null && ha2.length > 0) {
			for (int i = 0;i < ha2.length; i++) {
				cookies.addAll(HttpCookie.parse(ha2[i].getValue()));
			}
		}
		
		if (Log.DEBUG) {
			Log.d(TAG, cookies + "");
		}
		
		return cookies.toArray(new Cookie[0]);
	}

	
	public long getDateHeader(String name) {
		Header h = req.getLastHeader(name);
		if (h == null) {
			return -1;
		}
		try {
			return parseDate(h.getValue());
		} catch (Exception e) {
			throw new IllegalArgumentException(e);
		}
	}

	private long parseDate(String value) {
		return DateUtils.parseDate(value).getTime();
	}

	
	public String getHeader(String name) {
		Header h = req.getLastHeader(name);
		return h == null ? null : h.getValue();
	}

	
	public Enumeration<String> getHeaders(String name) {
		Header[] hs = req.getHeaders(name);
		ArrayList<String> hl = new ArrayList<String>();
		if (hs != null && hs.length > 0) {
			for (int i = 0; i < hs.length; i++) {
				String v = hs[i].getValue();
				if (v != null) {
					hl.add(v);
				}
			}
		}
		return Collections.enumeration(hl);
	}

	
	public Enumeration<String> getHeaderNames() {
		Header[] hs = req.getAllHeaders();
		ArrayList<String> hl = new ArrayList<String>();
		if (hs != null && hs.length > 0) {
			for (int i = 0; i < hs.length; i++) {
				hl.add(hs[i].getName());
			}
		}
		return Collections.enumeration(hl);
	}

	
	public int getIntHeader(String name) {
		Header h = req.getLastHeader(name);
		if (h == null) {
			return -1;
		}
		return Integer.parseInt(h.getValue());
	}

	
	public String getMethod() {
		return req.getRequestLine().getMethod();
	}

	
	public String getPathInfo() {
		String uri = req.getRequestLine().getUri();
		int idx1 = uri.indexOf("/", 1);
		int idx2 = uri.indexOf("?");
		return idx1 == -1 ? null : idx2 == -1 ? uri.substring(idx1) : uri
				.substring(idx1, idx2);
	}

	
	public String getPathTranslated() {
		return null;
	}

	
	public String getContextPath() {
		String uri = req.getRequestLine().getUri();
		if (uri.equals("/")) {
			return "";
		}
		int idx = uri.indexOf("/", 1);
		String p = idx == -1 ? uri : uri.substring(0, idx);
		return p;
	}

	
	public String getQueryString() {
		String uri = req.getRequestLine().getUri();
		int idx = uri.indexOf("?");
		return idx == -1 ? null : uri.substring(idx + 1);
	}

	
	public String getRemoteUser() {
		return null;
	}

	
	public boolean isUserInRole(String role) {
		return false;
	}

	
	public Principal getUserPrincipal() {
		return null;
	}

	
	public String getRequestedSessionId() {
		return null;
	}

	
	public String getRequestURI() {
		String uri = req.getRequestLine().getUri();
		return uri;
	}

	
	public StringBuffer getRequestURL() {
		StringBuffer sb = new StringBuffer();
		String scheme = getScheme();
		sb.append(scheme);
		sb.append("://");
		sb.append(getLocalName());
		int port = getLocalPort();
		sb.append(":");
		sb.append(port); // will not be able to use default 80 or 443
		sb.append(req.getRequestLine().getUri());
		return sb;
	}

	
	public String getServletPath() {
		// TODO
		return "/webdav";
	}

	
	public boolean isRequestedSessionIdValid() {
		return false;
	}

	
	public boolean isRequestedSessionIdFromCookie() {
		return true;
	}

	
	public boolean isRequestedSessionIdFromURL() {
		return false;
	}

	
	public boolean isRequestedSessionIdFromUrl() {
		return false;
	}

	
	public RequestDispatcher getRequestDispatcher(String path) {
		return null;
	}

	
	public HttpSession getSession(boolean create) {
		return null;
	}

	
	public HttpSession getSession() {
		return null;
	}

}
